package com.smt.modules.bus.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.smt.common.enums.Code;
import com.smt.common.utils.*;
import com.smt.modules.app.utils.FileSizeUtil;
import com.smt.modules.bus.dao.DocumentDao;
import com.smt.modules.bus.entity.*;
import com.smt.modules.bus.service.*;
import com.smt.modules.bus.vo.request.DocumentManageReq;
import com.smt.modules.bus.vo.DocumentVo;
import com.smt.modules.bus.vo.request.LoadFileReq;
import net.bytebuddy.asm.Advice;
import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.LocalDate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.print.Doc;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 文件上传
 *
 * @author zhangyi
 * @date 2018/10/8 12:05
 */
@Service("documentManageService")
public class DocumentManageServiceImpl extends ServiceImpl<DocumentDao, DocumentEntity> implements DocumentManageService {

    public static final String KB = "KB";
    public static final String MB = "MB";
    public static final long MAX_MB = 1024 * 1024;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private ProjectTaskService projectTaskService;

    @Autowired
    private SubtaskService subtaskService;

    @Autowired
    private DocPageService docPageService;

    /**
     *  保存用操作时间的间隔
     */
    Map<Long,Long> userOperateTime = new ConcurrentHashMap<>();

    /**
     * 上传文件存储信息
     *
     * @param docVo
     * @param docVo
     * @return
     */
    @Override
    public R upload(DocumentVo docVo) {
        if (Constant.FILE.equals(docVo.getStatusType()) &&
                !"null".equals(docVo.getFileUrl())) {
            File fileLocal = new File(docVo.getFileUrl());
            docVo.setName(fileLocal.getName());
            docVo.setCreateTime(DateTime.now().toDate());
            docVo.setUpdateTime(DateTime.now().toDate());
            String fileSize = FileSizeUtil.getFileSize(docVo.getFileUrl());
            if (StringUtils.contains(fileSize, KB)) {
                Double kb = Double.valueOf(fileSize.replace("KB", "").trim());
                docVo.setFileSize(kb / 1024);
            } else {
                Double mb = Double.valueOf(fileSize.replace("MB", "").trim());
                docVo.setFileSize(mb);
            }
            //初始化文件状态(驳回)
            docVo.setStatus(Constant.FILE_TURN_DOWN);
        } else if (Constant.DiRECTORY.equals(docVo.getStatusType())) {
            //文件夹
        }
        DocumentEntity documentEntity = new DocumentEntity();
        BeanUtils.copyProperties(docVo, documentEntity);
        boolean result = insert(documentEntity);
        if (result) {
            return R.ok();
        } else {
            return R.error(EnumToKeyUtil.toInt(Code.APPEND_DATA_ERROR), "文件新增失败");
        }
    }

    /**
     * 查询文件列表 我的文件
     *
     * @param userId
     * @param documentManageReq
     * @return
     */
    @Override
    public R list(DocumentManageReq documentManageReq, Long userId) {
        PageUtils pageUtils = null;
        Long projectId = documentManageReq.getProjectId();
        //项目文件集合,属于根目录文件
        if (userId.equals(documentManageReq.getMemberId())) {
            List<DocumentEntity> documentEntities = baseMapper.selectFileList(documentManageReq);
            List<DocumentEntity> docList = new LinkedList<>();
            documentEntities.stream()
                    .forEach(doc -> {
                        if (doc.getMemberId().equals(userId)) {
                            doc.setName(setFileName(doc.getName()));
                            docList.add(doc);
                        }
                    });
            Long parentId = documentManageReq.getParentId();
            if (parentId != null && parentId == 0) {
                List<AttachmentEntity> att = attachmentService.selectList(new EntityWrapper<AttachmentEntity>()
                        .eq("project_id", projectId)
                        .eq("uploaded_id", userId));
                //获取当前文件列表
                addFileList(att, docList);
            }

            //分页
            pageUtils = new PageUtils(docList, docList.size(), 10, 1);
        } else if (documentManageReq.getMemberId() == 0) {
            List<DocumentEntity> docs = selectList(new EntityWrapper<DocumentEntity>()
                    .eq("project_id", projectId)
                    .eq("parent_id", documentManageReq.getParentId())
                    .in("status", "0,1,50,401"));
            docs.stream()
                    .forEach(d -> {
                        d.setName(setFileName(d.getName()));
                    });
            Long parentId = documentManageReq.getParentId();
            if (parentId != null && parentId == 0) {
                List<AttachmentEntity> attachmentEntities = attachmentService.selectList(new EntityWrapper<AttachmentEntity>()
                        .eq("project_id", projectId));
                addFileList(attachmentEntities, docs);
            }
            pageUtils = new PageUtils(docs, docs.size(), 10, 1);
        }

        List<DocumentEntity> fatherIds = selectList(new EntityWrapper<DocumentEntity>()
                .eq("id", documentManageReq.getParentId()));
        Set<Long> fatherSet = new HashSet<>();
        fatherIds.stream().map(DocumentEntity::getParentId).forEach(p -> fatherSet.add(p));
        return R.ok().put("docs", pageUtils).put("fatherId", fatherSet);
    }

    /**
     * 下载文件
     *
     * @param fileId
     * @return
     */
    @Override
    public R download(Long fileId) {
        String filePath = null;
        DocumentEntity documentEntity = selectById(fileId);
        if (documentEntity != null) {
            filePath = documentEntity.getFileUrl();
        }
        return R.ok(filePath);
    }

    /**
     * 更新文件
     *
     * @param fileUrl
     * @param documentManageReq
     * @return
     */
    @Override
    public R update(String fileUrl, DocumentManageReq documentManageReq, MemberUserEntity memberUserEntity) {
        DocumentEntity documentEntity = new DocumentEntity();
        BeanUtils.copyProperties(documentManageReq, documentEntity);
        documentEntity.setUpdateTime(DateTime.now().toDate());
        documentEntity.setFileUrl(fileUrl);
        documentEntity.setMemberId(memberUserEntity.getUserId());
        documentEntity.setId(documentManageReq.getId());
        File file = new File(fileUrl);
        if (file.exists()) {
            long length = file.length();
            documentEntity.setFileSize(Double.valueOf(length / MAX_MB));
        } else {
            documentEntity.setFileSize(Double.valueOf(0));
        }
        boolean b = updateById(documentEntity);
        return b ? R.ok() : R.error(EnumToKeyUtil.toInt(Code.UPDATE_FAIL), "文件更新失败！");
    }

    /**
     * 删除文件
     *
     * @param fileId
     * @return
     */
    @Override
    public R delete(Long fileId) {
        //将文件状态设置为删除状态，方便以后可以找回
        DocumentEntity documentEntity = new DocumentEntity();
        documentEntity.setId(fileId);
        //删除
        documentEntity.setStatus(Constant.FILE_DELETE);
        boolean b = updateById(documentEntity);
        return b ? R.ok() : R.error(EnumToKeyUtil.toInt(Code.DELETE_DATA_ERROR), "文件删除失败！");
    }

    /**
     * 文件模糊查询
     *
     * @param fileName
     * @return
     */
    @Override
    public R search(Long projectId, String fileName) {
        List<DocumentEntity> documentEntities = selectList(new EntityWrapper<DocumentEntity>()
                .eq("project_id", projectId)
                .eq("status_type", 0)
                .like("name", fileName));
        documentEntities.stream()
                .forEach(d -> {
                    d.setName(setFileName(d.getName()));
                });
        //从项目文件中查找
        List<AttachmentEntity> attachmentEntities = attachmentService.selectList(new EntityWrapper<AttachmentEntity>()
                .eq("project_id", projectId)
                .like("file_name", fileName));
        attachmentEntities.stream()
                .forEach(a -> {
                    a.setFileName(setFileName(a.getFileName()));
                });
        addFileList(attachmentEntities, documentEntities);
        return R.ok().put("files", documentEntities);
    }

    /**
     * 获取文件打包实体,存储
     *
     * @param loadFileReq
     * @return
     */
    @Override
    public R docBackPage(LoadFileReq loadFileReq, MemberUserEntity memberUserEntity) {
        Long userId = memberUserEntity.getUserId();
        //设置打包间隔时间
        long dateTime = DateTime.now().toDate().getTime();
        long timeInterval = 5*Constant.SECOND_MS;
        if(Objects.isNull(userOperateTime.get(userId))){
            userOperateTime.put(userId,dateTime);
        }else{
            if(userOperateTime.get(userId)+timeInterval > dateTime){
                return R.ok("正在打包中，请稍后...");
            }else{
                userOperateTime.put(userId,dateTime);
            }
        }
        List<Long> taskIds = loadFileReq.getTaskIds();
        List<Long> subTaskIds = loadFileReq.getSubTaskIds();
        List<DocPageEntity> docPageEntities = new CopyOnWriteArrayList<>();
        if(taskIds != null && taskIds.size() != 0){
            for (Long t : taskIds) {
                //获取最新任务文件
                List<AttachmentEntity> attachmentEntities = attachmentService.selectList(new EntityWrapper<AttachmentEntity>()
                        .eq("project_task_id", t)
                        .orderBy("create_time", false));
                //任务id非空判断
                if (!Objects.isNull(attachmentEntities) && attachmentEntities.size() != 0) {
                    AttachmentEntity attachmentEntity = attachmentEntities.get(0);
                    Long projectTaskId = attachmentEntity.getProjectTaskId();
                    DocPageEntity docPageEntity = new DocPageEntity(
                            projectTaskId,
                            null,
                            attachmentEntity.getId(),
                            loadFileReq.getProjectId(),
                            memberUserEntity.getUserId(),
                            0,
                            loadFileReq.getPackName(),
                            DateTime.now().toDate());
                    docPageEntities.add(docPageEntity);
                }
            }
        }
        //插入子任务
        if(subTaskIds != null && subTaskIds.size() != 0){
            for(Long s : subTaskIds){
                //文件实体判断
                List<AttachmentEntity> subAttach = attachmentService.selectList(new EntityWrapper<AttachmentEntity>()
                        .eq("project_sub_task_id", s)
                        .orderBy("create_time", false));
                if (!Objects.isNull(subAttach) && subAttach.size() != 0) {
                    AttachmentEntity subAttachMent = subAttach.get(0);
                    DocPageEntity docPageEntity = new DocPageEntity(
                            null,
                            s,
                            subAttachMent.getId(),
                            loadFileReq.getProjectId(),
                            memberUserEntity.getUserId(),
                            0,
                            loadFileReq.getPackName(),
                            DateTime.now().toDate());
                    docPageEntities.add(docPageEntity);
                }
            }
        }
        boolean[] flag = new boolean[docPageEntities.size()];
        int[] i = new int[]{0};
        //添加批次标记
        long time = new Date(System.currentTimeMillis()).getTime();
        docPageEntities.stream().forEach(b -> {
            b.setBatch(String.valueOf(time)+memberUserEntity.getUserId());
            flag[i[0]++] = docPageService.insert(b);
        });
        for(boolean b : flag){
            if(!b){
                return R.error(EnumToKeyUtil.toInt(Code.UPDATE_FAIL), "文件打包错误");
            }
        }
        return R.ok("文件打包成功");
    }

    /**
     * 修改文件名
     *
     * @param fileName
     * @return
     */
    public String setFileName(String fileName) {
        if (StringUtils.contains(fileName, Constant.FILE_SPILT)) {
            String name = fileName.split(Constant.FILE_SPILT)[1];
            return name;
        }
        return fileName;
    }

    private void addFileList(List<AttachmentEntity> attachmentEntities, List<DocumentEntity> docs) {
        attachmentEntities.stream().forEach(a -> {
            DocumentEntity documentEntity = new DocumentEntity();
            documentEntity.setParentId(a.getParentId());
            documentEntity.setName(a.getFileName());
            documentEntity.setFileUrl(a.getUrl());
            documentEntity.setMemberId(a.getUploadedId());
            documentEntity.setFileSize(a.getFileSize());
            documentEntity.setProjectId(a.getProjectId());
            documentEntity.setFatherId(a.getParentId());
            documentEntity.setType(0);
            documentEntity.setStatusType(0);
            //添加文件状态
            //任务id
            Long projectTaskId = a.getProjectTaskId();
            //子任务id
            Long projectSubTaskId = a.getProjectSubTaskId();
            EntityWrapper<ProjectTaskEntity> projectTaskEntityEntityWrapper = new EntityWrapper<>();
            if (projectSubTaskId != null) {
                SubtaskEntity subtaskEntity = subtaskService.selectOne(new EntityWrapper<SubtaskEntity>()
                        .eq("id", projectSubTaskId));
                if (!Objects.isNull(subtaskEntity)) {
                    projectTaskEntityEntityWrapper.eq("id", subtaskEntity.getProjectTaskId());
                }
            } else if (projectTaskId != null) {
                projectTaskEntityEntityWrapper.eq("id", projectTaskId);
            }

            ProjectTaskEntity projectTaskEntity = projectTaskService.selectOne(projectTaskEntityEntityWrapper);
            if (projectTaskEntity != null) {
                documentEntity.setFileStage(projectTaskEntity.getStageId());
                documentEntity.setFileStatus(projectTaskEntity.getStatus());
            } else {
                documentEntity.setFileStage(0);
                documentEntity.setFileStatus(0);
            }
            docs.add(documentEntity);
        });
    }
}
